`include  "/home/zhoupu/ysyx-workbench/npc/vsrc/mduop.v"

module MDU (
  input [63:0] a_in,
  input [63:0] b_in,
  input [3:0] mdu_op_in,
  output reg [63:0] mdu_out,
  output overflow_out
);
  wire signed [63:0] a_signed_in, b_signed_in;
  wire [31:0] a_w_in, b_w_in;
  wire signed [31:0] a_signed_w_in, b_signed_w_in;
  wire [127:0] mul_out, mul_u_out, mul_su_out;
  wire [63:0] div_out, div_u_out, mul_w_out;
  wire [63:0] rem_out, rem_u_out;
  wire [31:0] div_w_out, div_uw_out, rem_w_out, rem_uw_out;

  assign a_signed_in = a_in;
  assign b_signed_in = b_in;
  assign a_w_in = a_in[31:0];
  assign b_w_in = b_in[31:0];
  assign a_signed_w_in = a_signed_in[31:0];
  assign b_signed_w_in = b_signed_in[31:0];

  assign mul_out    = a_signed_in * b_signed_in;
  assign mul_u_out  = a_in * b_in;
  assign mul_su_out = a_signed_in * b_in;
  assign mul_w_out  = a_signed_w_in * b_signed_w_in;

  assign div_out    = a_signed_in / b_signed_in;
  assign div_u_out  = a_in / b_in;
  assign div_w_out  = a_signed_w_in / b_signed_w_in;
  assign div_uw_out = a_w_in / b_w_in;

  assign rem_out    = a_signed_in % b_signed_in;
  assign rem_u_out  = a_in % b_in;
  assign rem_w_out  = a_signed_w_in % b_signed_w_in;
  assign rem_uw_out = a_w_in % b_w_in;

  assign overflow_out = 1'b0;

  MuxKeyWithDefault #(13, 4, 64) mdu_out_selector(mdu_out, mdu_op_in, rem_out, {
    `MDU_OP_MUL   , mul_out[63:0],
    `MDU_OP_MULH  , mul_out[127:64],
    `MDU_OP_MULHSU, mul_su_out[127:64],
    `MDU_OP_MULHU , mul_u_out[127:64],
    `MDU_OP_DIV   , div_out,
    `MDU_OP_DIVU  , div_u_out,
    `MDU_OP_REM   , rem_out,
    `MDU_OP_REMU  , rem_u_out,
    `MDU_OP_MULW  , {{32{mul_w_out[31]}}, mul_w_out[31:0]},
    `MDU_OP_DIVW  , {{32{div_w_out[31]}}, div_w_out},
    `MDU_OP_DIVUW , {{32{div_uw_out[31]}}, div_uw_out},
    `MDU_OP_REMW  , {{32{rem_w_out[31]}}, rem_w_out},
    `MDU_OP_REMUW , {{32{rem_uw_out[31]}}, rem_uw_out}
  });

endmodule